package com.rgs.pay.wechat.service;

import com.alibaba.fastjson.JSON;
import com.rgs.pay.wechat.util.HttpXmlUtils;
import com.rgs.pay.entity.SysPayKey;
import com.rgs.pay.wechat.util.WechatSignUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author Ren Gaoshuai
 * @ClassName WechatPayService
 * @date 2022-08-17 21:26
 * 微信支付流程
 * 准备支付参数
 * 对必要参数进行签名（准备签名工具类）
 * 调用微信支付接口
 * 解析微信支付返回参数
 **/
public class WechatPayService {

    public static final String TRADE_TYPE_JSAPI = "JSAPI";
    public static final String TRADE_TYPE_NATIVE = "NATIVE";
    public static final String TRADE_TYPE_H5 = "H5";
    public static final String TRADE_TYPE_APP = "APP";

    /**
     * 微信JSAPI下单支付
     * 支付地址：https://api.mch.weixin.qq.com/pay/unifiedorder V2版本
     * 文档地址：https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
     *
     * 支付地址：https://api.mch.weixin.qq.com/v3/pay/transactions/app  V3
     * 文档地址：https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_1.shtml
     *
     * @param // pay_title  支付标题
     * @param // out_trade_no  订单号
     * @param // total_fee  支付金额
     * @param // spbill_create_ip  生成订单的ip地址
     * @param // notify_url  回调地址  例：  https://tz.com/pay/notify/
     * @return Map 请看详细信息
     */
    public static Map<String, String> weChatJSAPIPay(Map<String, String> pa, SysPayKey sysPayKey) {
        System.out.println("===========================微信预下单开始==============================");
        Map<String, String> result = new HashMap<>();
        //随机字符
        String nonce_str = getRandomNum(8);
        String body = pa.get("pay_title");
        String openId = pa.get("openId");
        String attach = pa.get("attach");
        String total_fee = pa.get("total_fee");
        // "127.0.0.1";
        String spbill_create_ip = pa.get("spbill_create_ip").split(",")[0];
        String notify_url = sysPayKey.getWxNotifyUrl();
        // 参数：开始生成签名
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        //公众号
        parameters.put("appid", sysPayKey.getWxAppId());
        //商户号
        parameters.put("mch_id", sysPayKey.getWxMchId());
        //随机字符
        parameters.put("nonce_str", nonce_str);
        //商品描述
        parameters.put("body", body);
        //商户订单号，后台生成的商户订单号
        parameters.put("out_trade_no", pa.get("out_trade_no"));
        //金额：分
        parameters.put("total_fee", total_fee);
        //回调地址
        parameters.put("notify_url", notify_url);
        //交易类型 JSAPI -JSAPI；NATIVE -Native；APP -APP支付
        parameters.put("trade_type", TRADE_TYPE_JSAPI);
        //附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
        parameters.put("attach", attach + "-" + sysPayKey.getDeptId());
        //币种 固定CNY
        parameters.put("fee_type", "CNY");
        //用户标识，jsapi支付，必传
        parameters.put("openid", openId);
        //终端IP
        parameters.put("spbill_create_ip", spbill_create_ip);
        //签名
        String sign = WechatSignUtils.createSign("UTF-8", parameters, sysPayKey.getWxKey());
        parameters.put("sign", sign);
        // 构造xml参数，Map转xmlString
        String xmlInfo = HttpXmlUtils.xmlInfo(parameters);
        // 向微信发起下单
        String wechatResponse = HttpXmlUtils.httpsRequest(sysPayKey.getWxPayUrl(), xmlInfo);
        Map doXMLParse = null;
        String againSignStr = "";
        try {
            doXMLParse = HttpXmlUtils.doXMLParse(wechatResponse);
            if ("SUCCESS".equals(doXMLParse.get("return_code"))) {
                SortedMap<Object, Object> againParameters = new TreeMap<Object, Object>();
                againParameters.put("appId", doXMLParse.get("appid"));
                againParameters.put("signType", "MD5");
                againParameters.put("nonceStr", getRandomNum(8));
                againParameters.put("timeStamp", System.currentTimeMillis() / 1000);
                againParameters.put("package", "prepay_id=" + doXMLParse.get("prepay_id"));
                //再次签名
                String againSign = WechatSignUtils.createSign("UTF-8", againParameters, sysPayKey.getWxKey());
                againParameters.put("paySign", againSign);
                againSignStr = JSON.toJSONString(againParameters);
                System.out.println("再次签名结果" + againSignStr);
                result.put("code", "SUCCESS");
                result.put("msg", "下单成功");
                result.put("data", againSignStr);
                result.put("out_trade_no", pa.get("out_trade_no"));

            } else {
                result.put("code", "ERROR");
                result.put("msg", "签名失败");
            }

        } catch (Exception e) {

            e.printStackTrace();
        }
        result.put("service", "微信支付");
        System.out.println("==========================微信预下单完成===============================");
        return result;

    }

    /**
     * 生成随机数
     *
     * @param num 生成位数以固定8位
     * @return
     */
    public static String getRandomNum(int num) {
        int maxNum = 36;
        int i;
        int count = 0;
        char[] str = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
                'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
        StringBuffer pwd = new StringBuffer("");
        Random r = new Random();
        while (count < num) {
            i = Math.abs(r.nextInt(maxNum));
            if (i >= 0 && i < str.length) {
                pwd.append(str[i]);
                count++;
            }
        }
        return pwd.toString();
    }

}
